package ua.org.cityid.client.mvp;


import java.util.List;

import net.customware.gwt.dispatch.client.DispatchAsync;
import net.customware.gwt.presenter.client.EventBus;
import net.customware.gwt.presenter.client.place.Place;
import net.customware.gwt.presenter.client.place.PlaceRequest;
import net.customware.gwt.presenter.client.widget.WidgetDisplay;
import net.customware.gwt.presenter.client.widget.WidgetPresenter;
import ua.org.cityid.client.actions.GetCities;
import ua.org.cityid.client.actions.GetCitiesCount;
import ua.org.cityid.client.actions.GetCitiesCountResult;
import ua.org.cityid.client.actions.GetCitiesResult;
import ua.org.cityid.client.controls.RegionAnchor;
import ua.org.cityid.client.log.ILog;
import ua.org.cityid.shared.data.City;
import ua.org.cityid.shared.events.RegionChangedEvent;
import ua.org.cityid.shared.events.RegionChangedHandler;

import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.event.dom.client.HasClickHandlers;
import com.google.gwt.user.client.rpc.AsyncCallback;
import com.google.inject.Inject;

public class MainPresenter extends WidgetPresenter<MainPresenter.Display> {
	public static int MAX_VISIBLE_REGIONS = 20;
	private final DispatchAsync _dispatch;
	private final ILog _logger;
	private int currentRegionId = 0;
	private int currentRegionCitiesCount = 0;
	private int filterStartIntex = 0;
	
	public interface Display extends WidgetDisplay {
		void fillCitiesTable(List<City> cities);
		HasClickHandlers getNavBarNext();
		HasClickHandlers getNavBarPrev();
		
		List<RegionAnchor> getRegionAnchors();
		void updateNavBar(int itemsTotal, int startIndex);
	}

	@Inject
	public MainPresenter(final Display display,
			final EventBus eventBus,
			final DispatchAsync dispatch,
			final ILog logger) {
		super(display, eventBus);
		_dispatch = dispatch;
		_logger = logger;
	}

	@Override
	public Place getPlace() {
		// TODO Auto-generated method stub
		return null;
	}

	@Override
	protected void onBind() {
		registerRegionChangedEvent();
		registerHandler(display.getNavBarNext().addClickHandler(new ClickHandler() {
			@Override
			public void onClick(ClickEvent event) {
				_logger.info("filterStartIntex is " + filterStartIntex);
				filterStartIntex -= MAX_VISIBLE_REGIONS;
				if (filterStartIntex < 0)
					filterStartIntex = 0;
				_logger.info("filterStartIntex is " + filterStartIntex);
				requestCitiesofRegion();
			}
		}));
		
		registerHandler(display.getNavBarPrev().addClickHandler(new ClickHandler() {
			@Override
			public void onClick(ClickEvent event) {
				_logger.info("filterStartIntex is " + filterStartIntex);				
				filterStartIntex += MAX_VISIBLE_REGIONS;
				if (filterStartIntex > currentRegionCitiesCount)
					filterStartIntex = currentRegionCitiesCount;
				_logger.info("filterStartIntex is " + filterStartIntex);
				requestCitiesofRegion();
			}
		}));
		
		registerHandler(eventBus.addHandler(RegionChangedEvent.TYPE, new RegionChangedHandler() {
			@Override
			public void onRegionChanged(int regionId) {
				filterStartIntex = 0;
				currentRegionId = regionId;
				requestCitiesCount();
				requestCitiesofRegion();
			}

			private void requestCitiesCount() {
				_logger.info("requesting cities count");
				_dispatch.execute(new GetCitiesCount(currentRegionId), new AsyncCallback<GetCitiesCountResult>(){
					@Override
					public void onFailure(Throwable caught) {
						_logger.error("requesting cities count " + caught.toString());
					}

					@Override
					public void onSuccess(GetCitiesCountResult result) {
						_logger.info("got " + result.getClass().toString());
						currentRegionCitiesCount = result.getCitiesCount();
						_logger.info("total cities with regionid " + result.getRegionId() + " is " + result.getCitiesCount());
					}
				});
			}
		}));
		
		display.getRegionAnchors().get(0).switchSelectedRegion();
		eventBus.fireEvent(new RegionChangedEvent(0));
	}

	protected void requestCitiesofRegion() {
		_logger.info("requesting cities");
		_dispatch.execute(new GetCities(currentRegionId, filterStartIntex, MAX_VISIBLE_REGIONS), new AsyncCallback<GetCitiesResult>() {
			@Override
			public void onFailure(Throwable caught) {
				_logger.error("can't request cities." + caught.getLocalizedMessage());
			}

			@Override
			public void onSuccess(GetCitiesResult result) {
				_logger.info("got " + result.getClass().toString() + "total " + result.getCities().size());
				for (City c: result.getCities()){
					_logger.info("got city: " + c.getName() + " phonecode " + Integer.toString(c.getPhoneCode()));
				}
				display.fillCitiesTable(result.getCities());
				display.updateNavBar(currentRegionCitiesCount, MainPresenter.this.filterStartIntex);
			}
		});
	}

	private void registerRegionChangedEvent() {
		for (final RegionAnchor h : display.getRegionAnchors()) {
			registerHandler(h.getRegion().addClickHandler(new ClickHandler() {
				@Override
				public void onClick(ClickEvent event) {
					eventBus.fireEvent(new RegionChangedEvent(h.getRegionId()));
				}
			}));
		}
	}

//	void getLatestSavedRates() {
//		display.setShowLoadingCurrentRate(true);
//
//		final GetRates getRates = new GetRates();
//
//		_dispatch.execute(getRates, new AsyncCallback<GetRatesResult>() {
//
//			@Override
//			public void onFailure(final Throwable caught) {
//				display.setShowLoadingCurrentRate(false);
//				_logger.error("Unable to get saved rates: " + caught.getMessage());
//			}
//
//			@Override
//			public void onSuccess(final GetRatesResult result) {
//				display.setShowLoadingCurrentRate(false);
//				display.clearRecentRates();
//
//				for (final Rate rate : result.getRates()) {
//					display.addToRecentRates(rate, false);
//				}
//
//				// Put the latest rate in the box
//				if (result.getRates().size() > 0) {
//					final Rate latestRate = result.getRates().get(0);
//					display.getRateDisplayLabel().setText(String.valueOf(latestRate.getRate()));
//				}
//			}
//		});

//	}

//	void fetchSellingRate() {
//		display.setShowLoadingCurrentRate(true);
//		final CheckRate checkRate = new CheckRate(RateType.Selling);
//		_dispatch.execute(checkRate, new AsyncCallback<CheckRateResult>() {
//
//			@Override
//			public void onFailure(final Throwable caught) {
//				display.setShowLoadingCurrentRate(false);
//				_logger.error("Unable to fetch rate: " + caught.getMessage());
//			}
//
//			@Override
//			public void onSuccess(final CheckRateResult result) {
//				display.setShowLoadingCurrentRate(false);
//				// enable the fetch button
//				display.setEnabledFetchLatestButton(true);
//				display.getRateDisplayLabel().setText(String.valueOf(result.getRate().getRate()));
//				eventBus.fireEvent(new RateFetchedEvent(result.getRate()));
//			}
//
//		});
//
//		// disable the fetch button until RPC succeeds
//		display.setEnabledFetchLatestButton(false);
//	}
//
//	void saveRate(final Rate rate) {
//		final SaveRate saveRate = new SaveRate(rate);
//
//		_dispatch.execute(saveRate, new AsyncCallback<SaveRateResult>() {
//
//			@Override
//			public void onFailure(final Throwable caught) {
//				_logger.error("Unable to save rate: " + caught.getMessage());
//			}
//
//			@Override
//			public void onSuccess(final SaveRateResult result) {
//				eventBus.fireEvent(new RateSavedEvent(rate));
//			}
//
//		});
//
//	}

	@Override
	protected void onPlaceRequest(final PlaceRequest request) {
		// TODO Auto-generated method stub

	}

	@Override
	protected void onUnbind() {
		// TODO Auto-generated method stub

	}

	@Override
	public void refreshDisplay() {
		// TODO Auto-generated method stub

	}

	@Override
	public void revealDisplay() {
		// TODO Auto-generated method stub

	}
}
